package com.luckmgr.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.common.constant.SystemConstant;
import com.luckmgr.dto.ActivityDTO;
import com.luckmgr.dto.RecordDTO;
import com.luckmgr.entity.db.ActivityLevel;
import com.luckmgr.entity.db.LevelPrize;
import com.luckmgr.entity.db.LuckRecord;
import com.luckmgr.entity.db.LuckUser;
import com.luckmgr.entity.db.Prize;
import com.luckmgr.service.LevelPrizeService;
import com.luckmgr.service.LuckRecordService;
import com.luckmgr.service.LuckService;
import com.luckmgr.service.LuckUserService;
import com.luckmgr.system.SystemData;
import com.luckmgr.vo.AskLuckVO;

@Service
public class LuckServiceImpl implements LuckService {
	
	@Autowired
	LuckUserService luckUserService;
	
	@Autowired
	LuckRecordService luckRecordService;
	
	@Autowired
	LevelPrizeService levelPrizeService;
	
	private Logger logger = Logger.getLogger(LuckServiceImpl.class);

	@Override
	public AskLuckVO askAcivity(String acode, String uname) {
		AskLuckVO askLuckVO = new AskLuckVO();
		ActivityDTO activityDTO = SystemData.findActivityDTO(acode);
		if(null == activityDTO){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOACTIVITY);
			return askLuckVO;
		}
		
		LuckUser luckUser = luckUserService.findLuckUser(activityDTO.getActivity().getId(), uname);
		if(null == luckUser){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOUSER);
			return askLuckVO;
		}
		ActivityLevel activitylevel = activityDTO.getAcLevels().get(luckUser.getLevelId());
		if(null == activitylevel){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOLEVEL);
			return askLuckVO;
		}
		
		if(activitylevel.getLotteryNum()-luckUser.getUseNum()<=0){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NONUM);
			return askLuckVO;
		}
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("aid", activityDTO.getActivity().getId());
		map.put("name", luckUser.getUserName());
		List<LuckRecord> oldLuckRecord = luckRecordService.selectList(map);
		 
		
		RecordDTO recordDTO = LuckInit(activityDTO,oldLuckRecord,luckUser);
		if(null == recordDTO || null == recordDTO.getPrizeList()){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_ERROR);
			return askLuckVO;
		}
		askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_SUCCEED);
		askLuckVO.setUnm(recordDTO.getLuckUser().getEncryption());
		Integer excnum =  activityDTO.getAcLevels().get(recordDTO.getLuckUser().getLevelId()).getLotteryNum()-recordDTO.getLuckUser().getUseNum();
		askLuckVO.setLnum(excnum);
		return askLuckVO;
	}
	
	
	@Override
	public AskLuckVO luck(String acode, String euame,String ip) {
		AskLuckVO askLuckVO = new AskLuckVO();
		ActivityDTO activityDTO = SystemData.findActivityDTO(acode);
		if(null == activityDTO){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOACTIVITY);
			return askLuckVO;
		}
		
		RecordDTO recordDTO = activityDTO.getRecords().get(euame);
		
		if(null == recordDTO){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_LOGIN);
			return askLuckVO;
		}
		
		LuckUser luckUser = luckUserService.findLuckUser(activityDTO.getActivity().getId(), recordDTO.getLuckUser().getUserName());
		if(null == luckUser){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOUSER);
			return askLuckVO;
		}
		ActivityLevel activitylevel = activityDTO.getAcLevels().get(luckUser.getLevelId());
		if(null == activitylevel){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NOLEVEL);
			return askLuckVO;
		}
		
		if(luckUser.getUseNum()>=activitylevel.getLotteryNum()){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NONUM);
			return askLuckVO;
		}
		
		return lottery(activityDTO, luckUser, ip);
	}
	
	/**
	 * 
	 * @param activityDTO
	 * @param luckUser
	 */
	private RecordDTO LuckInit(ActivityDTO activityDTO,List<LuckRecord> oldLuckRecord,LuckUser luckUser){
		RecordDTO recordDTO = activityDTO.getRecords().get(luckUser.getEncryption());
		if(null == recordDTO){
			recordDTO = new RecordDTO();
			recordDTO.setLuckUser(luckUser);
			activityDTO.getRecords().put(luckUser.getEncryption(),recordDTO);
		}else{
			recordDTO.getLuckUser().setUseNum(luckUser.getUseNum());
		}
		
		recordDTO.getLock().lock();
		try {
			Integer excnum =  activityDTO.getAcLevels().get(recordDTO.getLuckUser().getLevelId()).getLotteryNum()-recordDTO.getLuckUser().getUseNum();
			if(excnum>0){
				List<Prize> luckPrizes =  recordDTO.getPrizeList();
				List<Prize> mustPrizes = new ArrayList<Prize>();
				if(luckPrizes ==null){
					if(luckUser.getUserValid()==1){
						mustPrizes = findMustPrizes(activityDTO,oldLuckRecord,recordDTO.getLuckUser());
					}
					List<Prize> randomPrizes = randomPrizes(activityDTO,oldLuckRecord,recordDTO.getLuckUser(), mustPrizes);
					luckPrizes = new ArrayList<Prize>();
					recordDTO.setPrizeList(luckPrizes);
					luckPrizes.addAll(mustPrizes);
					luckPrizes.addAll(randomPrizes);
					Collections.shuffle(luckPrizes);
					
					for(int i=0;i<luckPrizes.size();i++){
						Prize prize = luckPrizes.get(i);
						if(null != prize.getConsumeNum() && prize.getConsumeNum()>0){
							prize = luckPrizes.remove(i);
							luckPrizes.add(prize);
							break;
						}
					}
				
				}
				
			}
		} catch (Exception e) {
			logger.error("抽奖时报错：",e);
		}finally{
			recordDTO.getLock().unlock();
		}
		return recordDTO;
	}
	
	
	
	

	/**
	 * 获取内定奖品
	 * @param luckuser
	 * @return
	 */
	public List<Prize> findMustPrizes(ActivityDTO activityDTO,List<LuckRecord> oldLuckRecord,LuckUser luckuser){
		List<Prize> prizes = new ArrayList<Prize>();
		ActivityLevel activityLevel = activityDTO.getAcLevels().get(luckuser.getLevelId());
		Integer lucknum = activityLevel.getLotteryNum()-luckuser.getUseNum();
		for(LevelPrize levelPrize : activityLevel.getLeprizes()){
			if(null != levelPrize.getIdMin() && 0 !=levelPrize.getIdMin() && levelPrize.getAtomicPrizeNumber().get()>0){
				for(int i=0;i<levelPrize.getIdMin();i++){
					if(validPrize(levelPrize,oldLuckRecord, prizes, null)){
						Prize prize = activityDTO.getPrizes().get(levelPrize.getPrizeId());
						if(lucknum>=1){
							if(null !=prize.getConsumeNum() && 0!=prize.getConsumeNum()){
								--lucknum;
								activityLevel.getSumLuckNum().getAndDecrement();
							}
							levelPrize.getAtomicPrizeNumber().getAndDecrement();
							prizes.add(prize);
							if(lucknum<=0){
								return prizes;
							}
						}
					}
				}
			}
		}
		return prizes;
	}
	
	/**
	 * 随机奖品
	 * @param luckuser
	 * @param mustPrizes
	 * @return
	 */
	public List<Prize> randomPrizes(ActivityDTO activityDTO,List<LuckRecord> oldLuckRecord,LuckUser luckuser,List<Prize> mustPrizes){
		List<Prize> randmoPrize= new ArrayList<Prize>();
		ActivityLevel activityLevel = activityDTO.getAcLevels().get(luckuser.getLevelId());
		Integer mustnum = 0,remainnum = 0;
		for(Prize prize : mustPrizes){
			if(null != prize.getConsumeNum() && 0!=prize.getConsumeNum()){
				mustnum=mustnum+1;
			}
		}
		//剩于次数
		remainnum = (activityLevel.getLotteryNum()-luckuser.getUseNum()-mustnum);
		
		while (remainnum>0) {
			if(luckuser.getUserValid()==1){
				List<LevelPrize> levelPrizes = randomLevelPrizes(activityDTO,oldLuckRecord,luckuser.getLevelId(), mustPrizes, randmoPrize);
				Integer randmax = activityLevel.getSumLuckNum().get()+additionNum(activityDTO,activityLevel);
				if(randmax>0){
					int rand = new Random().nextInt(randmax)+1;
					Integer shifting = 0;
					boolean nullprize = true;
					
					for(LevelPrize levelPrize : levelPrizes){
						shifting +=levelPrize.getAtomicPrizeNumber().get();
						if(shifting>=rand){
							if(levelPrize.getAtomicPrizeNumber().get()>0 && activityLevel.getSumLuckNum().get()>0){
								nullprize = false;
								Prize prize = activityDTO.getPrizes().get(levelPrize.getPrizeId());
								levelPrize.getAtomicPrizeNumber().getAndDecrement();
								if(null != prize.getConsumeNum() && 0 != prize.getConsumeNum()){
									--remainnum;
									activityLevel.getSumLuckNum().getAndDecrement();
								}
								randmoPrize.add(prize);
								break;
							}
						}
					}
					
					if(nullprize){
						activityLevel.getSumLuckNum().getAndDecrement();
						randmoPrize.add(activityDTO.getnullPrize());
						--remainnum;
					}
				}else{
					activityLevel.getSumLuckNum().getAndDecrement();
					randmoPrize.add(activityDTO.getnullPrize());
					--remainnum;
				}
			}else{
				//抽奖总数 如果是黑名单会员 则总数不变化
				//activityLevel.getSumLuckNum().getAndDecrement();
				randmoPrize.add(activityDTO.getnullPrize());
				--remainnum;
			}
			
		
			
		}
		return randmoPrize;
	}
	
	/**
	 * 算出来消耗的数量
	 * @param activityDTO
	 * @param activityLevel
	 * @return
	 */
	private Integer additionNum(ActivityDTO activityDTO,ActivityLevel activityLevel){
		Integer addition = 0;
		for(LevelPrize levelPrize : activityLevel.getLeprizes()){
			Prize prize = activityDTO.getPrizes().get(levelPrize.getPrizeId());
			if(null ==prize.getConsumeNum() || 0 == prize.getConsumeNum()){
				addition+=levelPrize.getAtomicPrizeNumber().get();
			}
				
		}
		return addition;
	}
	
	/**
	 * 
		@param lid			奖品组id
	 * @param mustPrizes  	内定奖品
	 * @param randmoPrize	已随机奖品
	 * @param limitPrizes	限制的奖品
	 * @return	可供随机的奖品
	 */
	private List<LevelPrize> randomLevelPrizes(ActivityDTO activityDTO,List<LuckRecord> oldLuckRecord,Integer lid,List<Prize> mustPrizes,List<Prize> randmoPrize){
		List<LevelPrize> leprizes = new ArrayList<LevelPrize>();
		ActivityLevel activityLevel = activityDTO.getAcLevels().get(lid);
		for(LevelPrize lePrize : activityLevel.getLeprizes()){
			if(validPrize(lePrize,oldLuckRecord, mustPrizes, randmoPrize)){
				leprizes.add(lePrize);
			}
		}
		return leprizes;
	}
	
	private boolean validPrize(LevelPrize lePrize,List<LuckRecord> oldLuckRecord,List<Prize> mustPrizes,List<Prize> randmoPrize){
		if(lePrize.getAtomicPrizeNumber().get()<=0){
			return false;
		}
		if(null!=lePrize.getIdMax() && 0!=lePrize.getIdMax()){
			Integer havenum = 0;
			for(Prize prize: mustPrizes){
				if(lePrize.getPrizeId().equals(prize.getId())){
					++havenum;
				}
			}
			if(null !=randmoPrize){
				for(Prize prize: randmoPrize){
					if(lePrize.getPrizeId().equals(prize.getId())){
						++havenum;
					}
				}
			}
			
			if(null !=oldLuckRecord){
				for(LuckRecord luckRecord :oldLuckRecord){
					if(luckRecord.getPrizeId().equals(lePrize.getPrizeId())){
						++havenum;
					}
				}
			}
			
			if(0 != havenum && havenum>=lePrize.getIdMax()){
				return false;
			}else{
				return true;
			}
		}
		return true;
	}
	
	private List<LevelPrize> findLimitPrize(ActivityDTO activityDTO,Integer lid){
		List<LevelPrize> leprizes = new ArrayList<LevelPrize>();
		ActivityLevel activityLevel = activityDTO.getAcLevels().get(lid);
		for(LevelPrize lePrize : activityLevel.getLeprizes()){
			if(null!=lePrize.getIdMax() && 0!=lePrize.getIdMax()){
				leprizes.add(lePrize);
			}
		}
		return leprizes;
	}

	
	
	/*public AskLuckVO lottery (ActivityDTO activityDTO, RecordDTO recordDTO){
		AskLuckVO askLuckVO = new AskLuckVO();
		askLuckVO.setUnm(recordDTO.getLuckUser().getEncryption());
		Integer excnum =  activityDTO.getAcLevels().get(recordDTO.getLuckUser().getLevelId()).getLotteryNum()-recordDTO.getLuckUser().getUseNum();
		if(excnum<=0){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_NONUM);
			return askLuckVO;
		}
		
		if(null == recordDTO.getPrizeList() || 0 == recordDTO.getPrizeList().size()){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_LOGIN);
			return askLuckVO;
		}
		askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_SUCCEED);
		askLuckVO.setLnum(excnum);
		askLuckVO.setPix(recordDTO.getPrizeList().get(0).getPrizeIndex());
		return askLuckVO;
		
	}*/
	
	
	public AskLuckVO lottery (ActivityDTO activityDTO, LuckUser luckUser,String ip){
		AskLuckVO askLuckVO = new AskLuckVO();
		ActivityLevel activityLevel = activityDTO.getAcLevels().get(luckUser.getLevelId());
		RecordDTO recordDTO = activityDTO.getRecords().get(luckUser.getEncryption());
		if(null == recordDTO){
			askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_LOGIN);
			return askLuckVO;
		}else{
			recordDTO.getLuckUser().setUseNum(luckUser.getUseNum());
		}
		
		askLuckVO.setUnm(recordDTO.getLuckUser().getEncryption());
		recordDTO.getLock().lock();
		try {
			Integer excnum =  activityLevel.getLotteryNum()-recordDTO.getLuckUser().getUseNum();
			if(excnum>0){
				List<Prize> luckPrizes =  recordDTO.getPrizeList();
				if(luckPrizes ==null || 0 == luckPrizes.size()){
					askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_LOGIN);
					return askLuckVO;
				}
				Prize prize = recordDTO.getPrizeList().remove(0);
				
				LuckRecord luckRecord = new LuckRecord();
				luckRecord.setPrizeWay("系统抽取");
				luckRecord.setActivityId(activityDTO.getActivity().getId());
				luckRecord.setActivityName(activityDTO.getActivity().getName());
				luckRecord.setSeriesCode(activityDTO.getActivity().getSeriesCode());
				luckRecord.setStatus(0);
				luckRecord.setPrizeTime(new Date());
				luckRecord.setUserName(luckUser.getUserName());
				luckRecord.setEncryption(luckUser.getEncryption());
				luckRecord.setPrizeId(prize.getId());
				luckRecord.setPrizeName(prize.getPrizeName());
				luckRecord.setOperatorName(luckUser.getUserName());
				luckRecord.setOperatorIp(ip);
				
				if(-1 != prize.getId()){
					levelPrizeService.updatePrizeNum(activityDTO.getActivity().getId(), recordDTO.getLuckUser().getLevelId(), prize.getId());
				}
				luckRecordService.addEntity(luckRecord);
				if(null != prize.getConsumeNum() && prize.getConsumeNum()>0){
					luckUserService.updateUserAsk(luckUser.getId());
					recordDTO.getLuckUser().setUseNum(recordDTO.getLuckUser().getUseNum()+1);
				}
				if(null != prize.getShowPrize() && prize.getShowPrize()>0){
					SystemData.addLottoRecord(activityDTO.getActivity().getSeriesCode(), luckRecord);
				}
				
				askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_SUCCEED);
				askLuckVO.setPix(prize.getPrizeIndex());
				askLuckVO.setLnum(activityLevel.getLotteryNum()-recordDTO.getLuckUser().getUseNum());
				if(1==prize.getPrizeIndex()){
					askLuckVO.setMsg("很遗憾!"+prize.getPrizeName());
				}else{
					askLuckVO.setMsg("获得："+prize.getPrizeName());
				}
				
				
			}else{
				askLuckVO.setAs(SystemConstant.LUCK_ASK_STATUS_LOGIN);
				return askLuckVO;
			}
		} catch (Exception e) {
			logger.error("确认抽奖时：",e);
		}finally{
			recordDTO.getLock().unlock();
		}
		return askLuckVO;
	}

}
